package cn.com.twoke.easyproject.config.version;

import jakarta.servlet.http.HttpServletRequest;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.mvc.condition.RequestCondition;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static cn.hutool.core.text.CharSequenceUtil.compareVersion;

@Getter
@Slf4j
public class ApiVersionCondition implements RequestCondition<ApiVersionCondition> {

    private final static Pattern VERSION_PREFIX_PATTERN = Pattern.compile("v(\\d+(?:\\.\\d+){0,2})");

    private final String apiVersion;
    private final ApiVersionAccessPolicyEnum accessPolicy;

    public ApiVersionCondition(String apiVersion, ApiVersionAccessPolicyEnum accessPolicy) {
        this.apiVersion = fullVersion(apiVersion);
        this.accessPolicy = accessPolicy;
    }


    private String fullVersion(String apiVersion) {
        String[] versions = apiVersion.split("\\.");
        if (versions.length == 1) {
            apiVersion = apiVersion + ".0.0";
        } else if (versions.length == 2) {
            apiVersion = apiVersion + ".0";
        }
        return apiVersion;
    }


    @Override
    public ApiVersionCondition combine(ApiVersionCondition other) {
        return new ApiVersionCondition(other.getApiVersion(), other.getAccessPolicy());
    }

    @Override
    public ApiVersionCondition getMatchingCondition(HttpServletRequest request) {
        Matcher m = VERSION_PREFIX_PATTERN.matcher(request.getRequestURI());
        if (m.find()) {
            String version = fullVersion(m.group(1));
            switch(this.accessPolicy) {
                case SAME_VERSION_ACCESS -> {
                    if (compareVersion(version, this.apiVersion) == 0) {
                        return this;
                    }
                }
                case GREATER_OR_EQUAL_VERSION_ACCESS -> {
                    if (compareVersion(version, this.apiVersion) >= 0) {
                        return this;
                    }
                }
            }

        }
        return null;
    }


    @Override
    public int compareTo(ApiVersionCondition other, HttpServletRequest request) {
        return compareVersion(other.apiVersion, this.apiVersion);
    }
}
